home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / gfx / conv / jpegV5Asrc.lha / jpeg-5a / wrppm.c < prev    next >
C/C++ Source or Header  |  1994-11-11  |  8KB  |  269 lines

  1. /*
  2.  * wrppm.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to write output images in PPM/PGM format.
  9.  * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
  10.  * The PBMPLUS library is NOT required to compile this software
  11.  * (but it is highly useful as a set of PPM image manipulation programs).
  12.  *
  13.  * These routines may need modification for non-Unix environments or
  14.  * specialized applications.  As they stand, they assume output to
  15.  * an ordinary stdio stream.
  16.  */
  17.  
  18. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  19.  
  20. #ifdef PPM_SUPPORTED
  21.  
  22.  
  23. /*
  24.  * For 12-bit JPEG data, we either downscale the values to 8 bits
  25.  * (to write standard byte-per-sample PPM/PGM files), or output
  26.  * nonstandard word-per-sample PPM/PGM files.  Downscaling is done
  27.  * if PPM_NORAWWORD is defined (this can be done in the Makefile
  28.  * or in jconfig.h).
  29.  * (When the core library supports data precision reduction, a cleaner
  30.  * implementation will be to ask for that instead.)
  31.  */
  32.  
  33. #if BITS_IN_JSAMPLE == 8
  34. #define PUTPPMSAMPLE(ptr,v)  *ptr++ = (char) (v)
  35. #define BYTESPERSAMPLE 1
  36. #define PPM_MAXVAL 255
  37. #else
  38. #ifdef PPM_NORAWWORD
  39. #define PUTPPMSAMPLE(ptr,v)  *ptr++ = (char) ((v) >> (BITS_IN_JSAMPLE-8))
  40. #define BYTESPERSAMPLE 1
  41. #define PPM_MAXVAL 255
  42. #else
  43. /* The word-per-sample format always puts the LSB first. */
  44. #define PUTPPMSAMPLE(ptr,v)            \
  45.     { register int val_ = v;        \
  46.       *ptr++ = (char) (val_ & 0xFF);    \
  47.       *ptr++ = (char) ((val_ >> 8) & 0xFF);    \
  48.     }
  49. #define BYTESPERSAMPLE 2
  50. #define PPM_MAXVAL ((1<<BITS_IN_JSAMPLE)-1)
  51. #endif
  52. #endif
  53.  
  54.  
  55. /*
  56.  * When JSAMPLE is the same size as char, we can just fwrite() the
  57.  * decompressed data to the PPM or PGM file.  On PCs, in order to make this
  58.  * work the output buffer must be allocated in near data space, because we are
  59.  * assuming small-data memory model wherein fwrite() can't reach far memory.
  60.  * If you need to process very wide images on a PC, you might have to compile
  61.  * in large-memory model, or else replace fwrite() with a putc() loop ---
  62.  * which will be much slower.
  63.  */
  64.  
  65.  
  66. /* Private version of data destination object */
  67.  
  68. typedef struct {
  69.   struct djpeg_dest_struct pub;    /* public fields */
  70.  
  71.   /* Usually these two pointers point to the same place: */
  72.   char *iobuffer;        /* fwrite's I/O buffer */
  73.   JSAMPROW pixrow;        /* decompressor output buffer */
  74.   size_t buffer_width;        /* width of I/O buffer */
  75.   JDIMENSION samples_per_row;    /* JSAMPLEs per output row */
  76. } ppm_dest_struct;
  77.  
  78. typedef ppm_dest_struct * ppm_dest_ptr;
  79.  
  80.  
  81. /*
  82.  * Write some pixel data.
  83.  * In this module rows_supplied will always be 1.
  84.  *
  85.  * put_pixel_rows handles the "normal" 8-bit case where the decompressor
  86.  * output buffer is physically the same as the fwrite buffer.
  87.  */
  88.  
  89. METHODDEF void
  90. put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  91.         JDIMENSION rows_supplied)
  92. {
  93.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  94.  
  95.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  96. }
  97.  
  98.  
  99. /*
  100.  * This code is used when we have to copy the data and apply a pixel
  101.  * format translation.  Typically this only happens in 12-bit mode.
  102.  */
  103.  
  104. METHODDEF void
  105. copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  106.          JDIMENSION rows_supplied)
  107. {
  108.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  109.   register char * bufferptr;
  110.   register JSAMPROW ptr;
  111.   register JDIMENSION col;
  112.  
  113.   ptr = dest->pub.buffer[0];
  114.   bufferptr = dest->iobuffer;
  115.   for (col = dest->samples_per_row; col > 0; col--) {
  116.     PUTPPMSAMPLE(bufferptr, GETJSAMPLE(*ptr++));
  117.   }
  118.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  119. }
  120.  
  121.  
  122. /*
  123.  * Write some pixel data when color quantization is in effect.
  124.  * We have to demap the color index values to straight data.
  125.  */
  126.  
  127. METHODDEF void
  128. put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  129.           JDIMENSION rows_supplied)
  130. {
  131.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  132.   register char * bufferptr;
  133.   register int pixval;
  134.   register JSAMPROW ptr;
  135.   register JSAMPROW color_map0 = cinfo->colormap[0];
  136.   register JSAMPROW color_map1 = cinfo->colormap[1];
  137.   register JSAMPROW color_map2 = cinfo->colormap[2];
  138.   register JDIMENSION col;
  139.  
  140.   ptr = dest->pub.buffer[0];
  141.   bufferptr = dest->iobuffer;
  142.   for (col = cinfo->output_width; col > 0; col--) {
  143.     pixval = GETJSAMPLE(*ptr++);
  144.     PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0[pixval]));
  145.     PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1[pixval]));
  146.     PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2[pixval]));
  147.   }
  148.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  149. }
  150.  
  151.  
  152. METHODDEF void
  153. put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  154.            JDIMENSION rows_supplied)
  155. {
  156.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  157.   register char * bufferptr;
  158.   register JSAMPROW ptr;
  159.   register JSAMPROW color_map = cinfo->colormap[0];
  160.   register JDIMENSION col;
  161.  
  162.   ptr = dest->pub.buffer[0];
  163.   bufferptr = dest->iobuffer;
  164.   for (col = cinfo->output_width; col > 0; col--) {
  165.     PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)]));
  166.   }
  167.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  168. }
  169.  
  170.  
  171. /*
  172.  * Startup: write the file header.
  173.  */
  174.  
  175. METHODDEF void
  176. start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  177. {
  178.   ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
  179.  
  180.   /* Emit file header */
  181.   switch (cinfo->out_color_space) {
  182.   case JCS_GRAYSCALE:
  183.     /* emit header for raw PGM format */
  184.     fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n",
  185.         (long) cinfo->output_width, (long) cinfo->output_height,
  186.         PPM_MAXVAL);
  187.     break;
  188.   case JCS_RGB:
  189.     /* emit header for raw PPM format */
  190.     fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n",
  191.         (long) cinfo->output_width, (long) cinfo->output_height,
  192.         PPM_MAXVAL);
  193.     break;
  194.   default:
  195.     ERREXIT(cinfo, JERR_PPM_COLORSPACE);
  196.   }
  197. }
  198.  
  199.  
  200. /*
  201.  * Finish up at the end of the file.
  202.  */
  203.  
  204. METHODDEF void
  205. finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  206. {
  207.   /* Make sure we wrote the output file OK */
  208.   fflush(dinfo->output_file);
  209.   if (ferror(dinfo->output_file))
  210.     ERREXIT(cinfo, JERR_FILE_WRITE);
  211. }
  212.  
  213.  
  214. /*
  215.  * The module selection routine for PPM format output.
  216.  */
  217.  
  218. GLOBAL djpeg_dest_ptr
  219. jinit_write_ppm (j_decompress_ptr cinfo)
  220. {
  221.   ppm_dest_ptr dest;
  222.  
  223.   /* Create module interface object, fill in method pointers */
  224.   dest = (ppm_dest_ptr)
  225.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  226.                   SIZEOF(ppm_dest_struct));
  227.   dest->pub.start_output = start_output_ppm;
  228.   dest->pub.finish_output = finish_output_ppm;
  229.  
  230.   /* Calculate output image dimensions so we can allocate space */
  231.   jpeg_calc_output_dimensions(cinfo);
  232.  
  233.   /* Create physical I/O buffer.  Note we make this near on a PC. */
  234.   dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
  235.   dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF(char));
  236.   dest->iobuffer = (char *) (*cinfo->mem->alloc_small)
  237.     ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width);
  238.  
  239.   if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 ||
  240.       SIZEOF(JSAMPLE) != SIZEOF(char)) {
  241.     /* When quantizing, we need an output buffer for colormap indexes
  242.      * that's separate from the physical I/O buffer.  We also need a
  243.      * separate buffer if pixel format translation must take place.
  244.      */
  245.     dest->pub.buffer = (*cinfo->mem->alloc_sarray)
  246.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  247.        cinfo->output_width * cinfo->output_components, (JDIMENSION) 1);
  248.     dest->pub.buffer_height = 1;
  249.     if (! cinfo->quantize_colors)
  250.       dest->pub.put_pixel_rows = copy_pixel_rows;
  251.     else if (cinfo->out_color_space == JCS_GRAYSCALE)
  252.       dest->pub.put_pixel_rows = put_demapped_gray;
  253.     else
  254.       dest->pub.put_pixel_rows = put_demapped_rgb;
  255.   } else {
  256.     /* We will fwrite() directly from decompressor output buffer. */
  257.     /* Synthesize a JSAMPARRAY pointer structure */
  258.     /* Cast here implies near->far pointer conversion on PCs */
  259.     dest->pixrow = (JSAMPROW) dest->iobuffer;
  260.     dest->pub.buffer = & dest->pixrow;
  261.     dest->pub.buffer_height = 1;
  262.     dest->pub.put_pixel_rows = put_pixel_rows;
  263.   }
  264.  
  265.   return (djpeg_dest_ptr) dest;
  266. }
  267.  
  268. #endif /* PPM_SUPPORTED */
  269.